<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: 流年 <liu21st@gmail.com>
// +----------------------------------------------------------------------
use app\common\service\AliyunSmsService;
use app\common\service\RegionService;
use app\common\service\weChatApp\WeChatReleaseService;
use app\common\tools\SysEnums;
use app\interfaces\controller\TxLbs;
use think\facade\Request;

// 应用公共文件
function sqlTime($start_time, $end_time, $key, &$where, $strtotime = true)
{
    if (empty($key)) {
        return $where;
    }
    //按时间查询
    $start_time = trim($start_time);
    $end_time = trim($end_time);
    if (!empty($start_time) && !empty($end_time)) {
        if ($strtotime == true) {
            $start_time = strtotime($start_time);
            $end_time = strtotime($end_time . ' 23:59:59');
        } else {
            $end_time = $end_time + 86399;
        }
        $where[] = [$key, 'BETWEEN', [$start_time, $end_time]];
    } else {
        if (!empty($start_time)) {
            if ($strtotime == true) {
                $start_time = strtotime($start_time);
            }
            $where[] = [$key, '>=', $start_time];
        }
        if (!empty($end_time)) {
            if ($strtotime == true) {
                $end_time = strtotime($end_time . ' 23:59:59');
            } else {
                $end_time = $end_time + 86399;
            }
            $where[] = [$key, '<=', $end_time];
        }
    }
    return $where;
}

/**
 * url转二维码
 * @param type $url
 * @return string
 */
function qrcode($url)
{
    $file = RUNTIME_PATH . 'Cache/' . md5($url) . '.png';
    $cache = file_get_contents($file);
    if (empty($cache)) {
        $qrcode = new \Org\Qrcode\Qrcode();
        $qrcode::png($url, $file, QR_ECLEVEL_L, 3, 1);
        $cache = file_get_contents($file);
    }
    $file_content = base64_encode($cache); //base64编码的一个大字符串。。。
    $img = 'data:' . $type['mime'] . ';base64,' . $file_content; //合成图片的base64编码
    return $img;
}

/**
 * 获取时间范围
 * @param type $type
 * @return array
 */
function getTimeRange($type)
{
    $time = time();
    switch ($type) {
        case 1://本月
            $timestamp = $time;
            $mdays = date('t', $timestamp);
            $ret['sdate'] = date('Y-m-1 00:00:00', $timestamp);
            $ret['edate'] = date('Y-m-' . $mdays . ' 23:59:59', $timestamp);
            break;
        case 2://本季度
            $season = ceil((date('n')) / 3);//当月是第几季度
            $ret['sdate'] = date('Y-m-d H:i:s', mktime(0, 0, 0, $season * 3 - 3 + 1, 1, date('Y')));//本季度第一天
            $ret['edate'] = date('Y-m-d H:i:s', mktime(23, 59, 59, $season * 3, date('t', mktime(0, 0, 0, $season * 3, 1, date("Y"))), date('Y')));//本季度最后一天
            break;
        case 3://本年
            $ret['sdate'] = date('Y-m-d H:i:s', strtotime(date('Y') . '-1-1 0:0:0'));
            $ret['edate'] = date('Y-m-d H:i:s', strtotime((date('Y') + 1) . '-1-1 0:0:0') - 1);
            break;
        case 4://上个月
            $timestamp = strtotime(date('Y-m-1')) - 86400;
            $mdays = date('t', $timestamp);
            $ret['sdate'] = date('Y-m-1 00:00:00', $timestamp);
            $ret['edate'] = date('Y-m-' . $mdays . ' 23:59:59', $timestamp);
            break;
        case 5://上个季度
            $season = ceil((date('n')) / 3) - 1;//上季度是第几季度
            $ret['sdate'] = date('Y-m-d H:i:s', mktime(0, 0, 0, $season * 3 - 3 + 1, 1, date('Y')));//上季度第一天
            $ret['edate'] = date('Y-m-d H:i:s', mktime(23, 59, 59, $season * 3, date('t', mktime(0, 0, 0, $season * 3, 1, date("Y"))), date('Y')));//上季度最后一天
            break;
        case 6://上一年
            $ret['sdate'] = date('Y-m-d H:i:s', strtotime((date('Y') - 1) . '-1-1 0:0:0'));
            $ret['edate'] = date('Y-m-d H:i:s', strtotime(date('Y') . '-1-1 0:0:0') - 1);
            break;
        case 7://昨天
            $timestamp = $time - 86400;
            $mdays = date('Y-m-d', $timestamp);
            $ret['sdate'] = date('Y-m-d', $timestamp);
            $ret['edate'] = date('Y-m-d 23:59:59', $timestamp);
            break;
        case 8://前4周
            $now_w = date("w");
            if ($now_w == 1) {
                $ret['sdate'] = date('Y-m-d', strtotime('-3 Monday'));
            } else {
                $ret['sdate'] = date('Y-m-d', strtotime('-4 Monday'));
            }
            $ret['edate'] = date('Y-m-d 23:59:59', time());
            break;
        case 9://本周
            $timestamp = $time;
            $w = date('w', $timestamp);
            $w = ($w + 6) % 7;
            $ret['sdate'] = date('Y-m-d', strtotime('-' . $w . ' day'));
            $ret['edate'] = date('Y-m-d 23:59:59', strtotime('-' . ($w - 6) . ' day'));
            break;
        case 10: // 近半年
            $ret['sdate'] = date('Y-m-01 00:00:00', strtotime('-5 month'));
            $ret['edate'] = date('Y-m-d 23:59:59', $time);
            break;
        default://默认今天
            $timestamp = $time;
            $mdays = date('Y-m-d', $timestamp);
            $ret['sdate'] = date('Y-m-d', $timestamp);
            $ret['edate'] = date('Y-m-d', $timestamp + 86400);
            break;
    }
    $rs['s_time'] = strtotime($ret['sdate']);
    $rs['e_time'] = strtotime($ret['edate']);
    return $rs;
}

/**
 * 根据内容截取摘要
 * @param type $content 需截取内容
 * @param type $limit 截取摘要的字数
 * @return null
 */
function getDigestByContent($content, $limit = 100)
{
    if ($content) {
        $digest = strip_tags(htmlspecialchars_decode($content, ENT_QUOTES));
        $digest = str_replace('&nbsp;', '', $digest);
        $limit = $limit > 0 ? $limit : 100;
        return mb_substr(trim($digest), 0, $limit, 'utf-8');
    }
    return '';
}

function array_sort($arr, $keys, $type = 'asc')
{
    $keysvalue = $new_array = array();
    foreach ($arr as $k => $v) {
        $keysvalue[$k] = $v[$keys];
    }
    if ($type == 'asc') {
        //对数组进行排序并保持索引关系
        asort($keysvalue);
    } else {
        //对数组进行逆向排序并保持索引关系
        arsort($keysvalue);
    }
    foreach ($keysvalue as $k => $v) {
        $new_array[] = $arr[$k];
    }
    return $new_array;
}

function getRandomCode($length = 10)
{
    $length = intval($length);
    $length = $length > 0 ? $length : 10;
    return substr(str_shuffle("0123456789"), 0, $length);
}

function getRandomString($length = 10)
{
    $length = intval($length);
    $length = $length > 0 ? $length : 10;
    return substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, $length);
}

/*根据月份数字获取中文名称*/
function getMonthByNum($month)
{
    switch ($month) {
        case '01':
            $rs = '一';
            break;
        case '02':
            $rs = '二';
            break;
        case '03':
            $rs = '三';
            break;
        case '04':
            $rs = '四';
            break;
        case '05':
            $rs = '五';
            break;
        case '06':
            $rs = '六';
            break;
        case '07':
            $rs = '七';
            break;
        case '08':
            $rs = '八';
            break;
        case '09':
            $rs = '九';
            break;
        case '10':
            $rs = '十';
            break;
        case '11':
            $rs = '十一';
            break;
        case '12':
            $rs = '十二';
            break;
        default:
            $rs = '';
            break;
    }
    return $rs;
}

/*根据年月获取对应月份的时间范围*/
function getRangeByMonth($year, $month, $tostr = 0)
{
    if ($year <= 0 || $month <= 0) {
        return false;
    }
    $start_time = mktime(0, 0, 0, $month, 1, $year);
    $end_time = mktime(23, 59, 59, ($month + 1), 0, $year);
    if ($tostr == 1) {
        $rs = ['s_time' => date('Y-m-d H:i:s', $start_time), 'e_time' => date('Y-m-d H:i:s', $end_time)];
    } elseif ($tostr == 2) {
        $rs = ['s_time' => date('Y-m-d', $start_time), 'e_time' => date('Y-m-d', $end_time)];
    } else {
        $rs = ['s_time' => $start_time, 'e_time' => $end_time];
    }
    return $rs;
}

/**
 * 检验是否是手机号码
 * @param type $mobile
 * @return boolean
 */
function is_mobile($mobile)
{
    if (preg_match("/^1[3-9][0-9]{9}$/", $mobile)) {
        return true;
    } else {
        return false;
    }
}

/**
 * 文件下载方法
 * @param type $file
 * @param type $file_name
 * @return boolean
 */
function downloadFile($file, $file_name = '')
{
    //初始化curl连接
    $curl = curl_init($file);
    curl_setopt($curl, CURLOPT_NOBODY, true);
    curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'GET');
    $result = curl_exec($curl);
    $bool = false;
    // 如果请求没有发送失败并且http响应码为200
    if ($result !== false && curl_getinfo($curl, CURLINFO_HTTP_CODE) == 200) {
        $bool = true;
    }
    //关闭curl连接
    curl_close($curl);
    //检验文件是否存在
    if ($bool === true) {
        //设置文件名称
        if ($file_name == '') {
            $file_name = pathinfo($file, PATHINFO_BASENAME);
        } else {
            $file_name = strpos($file_name, '.') ? $file_name : ($file_name . '.' . pathinfo($file, PATHINFO_EXTENSION)); //补充文件后缀
        }
        //通过文件头信息获取文件大小
        $header_array = get_headers($file, true);
        //设置header信息让浏览器识别并下载文件
        header('Content-Description: File Transfer');
        if (pathinfo($file, PATHINFO_EXTENSION) == 'mp3') {
            header('Content-Type: audio/mpeg');
        } else {
            header('Content-Type: application/octet-stream');
        }
        header('Content-Disposition: attachment; filename=' . $file_name);
        header('Content-Transfer-Encoding: binary');
        header('Expires: 0');
        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
        header('Pragma: public');
        header('Accept-Ranges: bytes');
        header('Content-Length: ' . $header_array['Content-Length']);
        header('Content-Range: bytes 0-' . ($header_array['Content-Length'] - 1) . '/' . $header_array['Content-Length']);
        ob_clean();
        flush();
        readfile($file);
        exit;
    } else {
        return false;
    }
}

/**
 * 随机验证码
 * @param type $length
 * @return string
 */
function rand_code($length = 8)
{
    // 密码字符集
    $chars = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '9', '8', '7', '6', '5', '4', '3', '2', '1', '0');
    // 在 $chars 中随机取 $length 个数组元素键名
    $keys = array_rand($chars, $length);
    $password = '';
    for ($i = 0; $i < $length; $i++) {
        // 将 $length 个数组元素连接成字符串
        $password .= $chars[$keys[$i]];
    }
    return $password;
}


/**
 * 生成layui子孙树
 * @param $data
 * @return array
 */
function makeTree($data)
{

    $res = [];
    $tree = [];

    // 整理数组
    foreach ($data as $key => $vo) {
        $res[$vo['id']] = $vo;
        $res[$vo['id']]['children'] = [];
    }
    unset($data);

    // 查询子孙
    foreach ($res as $key => $vo) {
        if ($vo['pid'] != 0) {
            $res[$vo['pid']]['children'][] = $res[$key];
        }
    }

    // 去除杂质
    foreach ($res as $key => $vo) {
        if (isset($vo['pid']) && $vo['pid'] == 0) {
            $tree[] = $vo;
        }
    }
    unset($res);

    return $tree;
}

//admin后台统一返回值
function adminOut($res)
{
    return json(successReturn($res));
}

/**
 * 将结果集对外输出
 * @param $resultData
 * @return null
 * @author sx
 */
function apiOut($resultData)
{
    $returnData = [
        'result' => true,
        'msg' => '',
        'code' => 0,
        'data' => []
    ];

    //header("Access-Control-Allow-Origin: *"); // 允许任意域名发起的跨域请求
    $returnData = array_merge($returnData, $resultData);
    if (Request::isPost() || Request::isAjax()) {//ajax或post才输出json编码的值
        return json($returnData);
    } else {
        echo '<pre>';
        print_r($returnData);
        echo '</pre>';
        exit;
    }
}

function apiOutError($msg = 'error', $code = \app\common\tools\SysEnums::AffairError, $data = [])
{
    return json([
        'result' => false,
        'msg' => $msg,
        'code' => $code,
        'data' => $data
    ]);
}

/**
 * @param int $code
 * @param array $data
 * @return \think\response\Json
 * User: cwh  DateTime:2020/11/22 13:17
 */
function appOut($code = \app\common\tools\SysEnums::AffairError, $data = [])
{
    return json([
        'result' => true,
        'msg' => \app\common\tools\ReturnCode::$_codeList[$code]['msg'],
        'code' => 0,
        'bizCode' => $code,
        'data' => $data
    ]);
}

/**
 * @param int $code
 * @param array $data
 * @return \think\response\Json
 * User: cwh  DateTime:2020/11/22 13:17
 */
function appOutError($code = \app\common\tools\SysEnums::AffairError, $data = [])
{
    return json([
        'result' => false,
        'msg' => \app\common\tools\ReturnCode::$_codeList[$code]['msg'] ?? '',
        'code' => 0,
        'bizCode' => $code,
        'data' => $data
    ]);
}

/**
 * 内部调用的 错误结果集
 * @param string $msg
 * @param int $code
 * @param array $resultData
 * @return array
 * User: 宋星 DateTime: 2020/10/27 10:31
 */
function errorReturn($obj = 'error', $code = \app\common\tools\SysEnums::AffairError, $resultData = [])
{
    $returnData = [
        'result' => false,
        'msg' => 'error',
        'code' => \app\common\tools\SysEnums::AffairError,
        'data' => []
    ];
    if (is_array($obj)) {
        $returnData = array_merge($returnData, $obj);
        $returnData['result'] = false;
        return $returnData;
    }
    if (is_string($obj)) {
        $returnData['msg'] = $obj;
    }
    $returnData['code'] = $code;
    $returnData = array_merge($returnData, $resultData);

    return $returnData;
}

/**
 * Notes: 内部调用的 成功结果集
 * @param $obj
 * @param int $code
 * @param array $resultData
 * @return array
 * User: SongX DateTime: 2021/7/8 10:30
 */
function successReturn($obj, $code = 0, $resultData = [])
{
    $returnData = [
        'result' => true,
        'msg' => '',
        'code' => 0,
        'data' => []
    ];
    if (is_array($obj)) {
        $returnData = array_merge($returnData, $obj);
        return $returnData;
    }
    if (is_string($obj)) {
        $returnData['msg'] = $obj;
    }
    $returnData['code'] = $code;
    $returnData = array_merge($returnData, $resultData);

    return $returnData;
}

/**
 * 跳出成功输出
 * @param $obj
 * @param int $code
 * @param array $resultData
 */
function successAbortReturn($obj, $code = 0, $resultData = [])
{
    return abort(response(successReturn($obj, $code, $resultData), 200, [], 'json'));
}

/**
 * 跳出错误输出
 * @param string $obj
 * @param int $code
 * @param array $resultData
 */
function errorAbortReturn($obj = 'error', $code = \app\common\tools\SysEnums::AffairError, $resultData = [])
{
    return abort(response(errorReturn($obj, $code, $resultData), 200, [], 'json'));
}

/**
 * 把数据库存储的相对路径地址转换成云空间地址
 * @param $img
 * @param $type
 * @return mixed
 */
function setImgUrl($img, $type = 1)
{
    $domain = env('oss.oss_domain');
    $spare_domain = request()->server('HTTP_HOST');
    $temp_domain = explode('.', $spare_domain);
    if (!empty($spare_domain) && ($temp_domain[1] == 'meijiabang' || $temp_domain[2] == 'meijiabang')) {
        $domain = str_replace('.zzsupei.', '.meijiabang.', $domain);
    }
    if (empty($img)) {
        return 'https://' . $domain . '/static/images/noimg.jpg';
    }
    if (is_array($img)) {
        $img = array_map(function ($v) use ($domain) {
            $type = (strpos($v, '/') === 0) ? 1 : 2;
            if ($type == 2) {
                $domain = env('oss.oss_zzsp_domain');
            }
            if (strpos($v, 'http://') !== false || strpos($v, 'https://') !== false) {
                return $v;
            }
            if (strpos($v, '/') > 0 || strpos($v, '/') === false) {
                $v = '/' . $v;
            }
            return 'https://' . $domain . $v;
        }, $img);
        return $img;
    } else {
        $type = (strpos($img, '/') === 0) ? 1 : 2;
        if ($type == 2) {
            $domain = env('oss.oss_zzsp_domain');
        }
        if (strpos($img, 'http://') !== false || strpos($img, 'https://') !== false) {
            return $img;
        }
        if (strpos($img, '/') > 0 || strpos($img, '/') === false) {
            $img = '/' . $img;
        }
        return 'https://' . $domain . $img;
    }
}

/**
 * 把URL转换成成云空间地址
 * @param string $url
 * @return string
 */
function getImgUrl(string $url)
{
    $domain = env('oss.oss_domain');
    $tempArr = explode($domain, $url);
    if (count($tempArr) > 1) {
        $tempUrl = $tempArr[1];
    } else {
        $tempUrl = $tempArr[0];
    }

    return $tempUrl;
}

/**
 * 二维数组根据某个字段进行分组
 * @param $arr
 * @param $key //要分组的字段, 例如 parent_id
 * @param string $col_id //每个元素的key
 * @return array
 * User: 宋星 DateTime: 2020/10/29 10:46
 */
function array_group_by($arr, $key, $col_id = 'id')
{
    $grouped = array();
    foreach ($arr as $value) {
        $grouped[$value[$key]][$value[$col_id]] = $value;
    }
    if (func_num_args() > 2) {
        $args = func_get_args();
        foreach ($grouped as $key => $value) {
            $parms = array_merge($value, array_slice($args, 2, func_num_args()));
            $grouped[$key] = call_user_func_array('array_group_by', $parms);
        }
    }
    return $grouped;
}

//从数组中取出指定键值的数据
function pick_from_array($array, $keys = [])
{
    if (empty($keys)) {
        return $array;
    }
    $rs = [];
    foreach ($keys as $key) {
        $rs[$key] = $array[$key];
    }
    return $rs;
}

/**
 * 获取周一到周日 数组
 * @author: lwj
 * @date: 2021/4/30 10:53
 */
function get_week_list($type = 1)
{
    if ($type == 1) {
        $week = [
            0 => '周一',
            1 => '周二',
            2 => '周三',
            3 => '周四',
            4 => '周五',
            5 => '周六',
            6 => '周日'
        ];
    } else {
        $week = [
            0 => '星期一',
            1 => '星期二',
            2 => '星期三',
            3 => '星期四',
            4 => '星期五',
            5 => '星期六',
            6 => '星期日'
        ];
    }
    return $week;
}

if (!function_exists('redis')) {
    /**
     * 获取容器对象实例
     * @return Redis
     */
    function redis()
    {
        return \app\common\tools\Redis::redis();
    }
}

if (!function_exists('pr')) {
    /**
     * Description:打印数据
     * User: Vijay <1937832819@qq.com>
     * Date: 2020/11/14
     * Time: 15:47
     * @param $data
     * @param int $choice
     */
    function pr($data, $choice = 1)
    {
        if ($choice == 1) {
            echo "<pre>";
            print_r($data);
            echo "</pre>";
        } elseif ($choice == 2) {
            dump($data, true, null);
        } else {
            echo "<pre>";
            var_export($data);
            echo "</pre>";
        }
        exit;
    }
}

if (!function_exists('pj')) {
    /**
     * Description:打印数据
     * User: Vijay <1937832819@qq.com>
     * Date: 2020/11/14
     * Time: 15:47
     * @param $data
     * @param int $choice
     */
    function pj($data, $isExit = 1)
    {
        echo "<pre>";
        echo json_encode($data);
        echo "<pre>";
        if ($isExit) exit;
    }
}

if (!function_exists('getTimeFormat')) {
    /**
     * Description:返回时间格式
     * User: Vijay <1937832819@qq.com>
     * Date: 2020/11/14
     * Time: 15:48
     * @param string $day today、yesterday、before_yesterday等
     * @param string $start_time 开始时间
     * @param string $end_time 结束时间
     * @param string $param 其他参数
     * @return array
     */
    function getTimeFormat($day = 'today', $start_time = '', $end_time = '', $param = '')
    {
        $start_time_str = strtotime(date('Y-m-d'));
        $end_time_str = strtotime(date('Y-m-d', strtotime('+1 day'))) - 1;
        $start_time = trim($start_time);
        $end_time = trim($end_time);
        if ($start_time != '' && $end_time != '') {
            //有具体开始时间和结束时间,直接获取字符串
            $start_time_str = strtotime($start_time);
            $end_time_str = strtotime($end_time);
            if ($start_time_str == $end_time_str) {
                $end_time_str = $end_time_str + 86400 - 1;
            }
            $end_time_zone = strtotime(date('Y-m-d', $end_time_str));
            if ($end_time_zone == $end_time_str) {
                $end_time_str = $end_time_str + 86400 - 1;
            }
        } else {
            if ($day != '') {
                if (is_numeric($day)) {
                    //数字格式直接返回近几天,如 -7为近7天
                    if ($day > 0) {
                        $day = '-' . $day;
                    }
                    if ($day < 0) {
                        $day += 1;
                    }
                    $start_time_str = strtotime(date('Y-m-d', strtotime($day . ' day')));
                    $end_time_str = strtotime(date('Y-m-d')) + 86400;
                } elseif (is_string($day)) {
                    switch ($day) {
                        case 'today'://今天
                            $start_time_str = strtotime(date('Y-m-d'));
                            $end_time_str = strtotime(date('Y-m-d', strtotime('+1 day'))) - 1;
                            break;
                        case 'yesterday'://昨天
                            $start_time_str = strtotime(date('Y-m-d', strtotime('-1 day')));
                            $end_time_str = strtotime(date('Y-m-d')) - 1;
                            break;
                        case 'before_yesterday'://前天
                            $start_time_str = strtotime(date('Y-m-d', strtotime('-2 day')));
                            $end_time_str = strtotime(date('Y-m-d', strtotime('-1 day'))) - 1;
                            break;
                        case 'this_week'://本周
                            $start_time_str = strtotime(date("Y-m-d H:i:s", mktime(0, 0, 0, date("m"), date("d") - date("w") + 1, date("Y"))));
                            $end_time_str = strtotime(date("Y-m-d H:i:s", mktime(23, 59, 59, date("m"), date("d") - date("w") + 7, date("Y"))));
                            break;
                        case 'now_month'://本月
                            $start_time_str = strtotime(date('Y-m-01'));
                            $end_time_str = strtotime(date('Y-m-01') . "+1 month -1 day");
                            break;
                        case 'per_month'://上月
                            $start_time_str = strtotime(date('Y-m-01', strtotime('-1 month')));
                            $end_time_str = strtotime(date('Y-m-01'));
                            break;
                        case 'pre_week'://上周 注意我们是从周一开始算
                            $start_time_str = strtotime(date('Y-m-d', strtotime('-2 week Monday')));
                            $end_time_str = strtotime(date('Y-m-d', strtotime('-1 week Monday +1 day')));
                            break;
                        case 'pre_year'://去年
                            $start_time_str = strtotime(date('Y-01-01', strtotime('-1 year')));
                            $end_time_str = strtotime(date('Y-12-31', strtotime('-1 year')));
                            break;
                        case 'now_year'://今年
                            $start_time_str = strtotime(date('Y-01-01'));
                            $end_time_str = strtotime(date('Y-m-d', strtotime('+1 day')));
                            break;
                        case 'quarter'://季度
                            $quarter = empty($param) ? ceil((date('n')) / 3) : $param;//获取当前季度
                            $start_time_str = mktime(0, 0, 0, $quarter * 3 - 2, 1, date('Y'));
                            $end_time_str = mktime(0, 0, 0, $quarter * 3 + 1, 1, date('Y'));
                            break;
                        default:
                            $start_time_str = strtotime(date('Y-m-d'));
                            $end_time_str = strtotime(date('Y-m-d', strtotime('+1 day'))) - 1;
                            break;
                    }
                }
            }
        }
        $start_time = date('Y-m-d H:i:s', $start_time_str);
        $end_time = date('Y-m-d H:i:s', $end_time_str);
        $res = [
            'start_time' => $start_time,
            'end_time' => $end_time,
            'start_time_str' => $start_time_str,
            'end_time_str' => $end_time_str,
        ];
        return $res;
    }
}

if (!function_exists('groupSameKey')) {
    /**
     * Notes:根据key分组
     * @param $arr
     * @param $key
     * @return array
     * @User: qc  DateTime: 2020/11/23 9:16
     */
    function groupSameKey($arr, $key)
    {
        $new_arr = array();
        foreach ($arr as $k => $v) {
            if (isset($v[$key])) {
                $new_arr[$v[$key]][] = $v;
            }
        }
        return $new_arr;
    }
}


if (!function_exists('relationArrayMerge')) {
    /**
     * Notes:关联数组合并
     * @param array $main_arr 主数组
     * @param array $relation_arr 关联数组
     * @param string $relation_key 关联key
     * @param string $relation_name 关联名称
     * @param string $relation_arr_primary 关联主键
     * @return array
     * @User: qc  DateTime: 2020/11/24 16:16
     */
    function relationArrayMerge(array $main_arr, array $relation_arr, string $relation_key, string $relation_name, string $relation_arr_primary = 'id')
    {
        $relation_arr = array_column($relation_arr, null, $relation_arr_primary);
        array_walk($main_arr, function (&$item) use ($relation_name, $relation_arr, $relation_key) {
            $item[$relation_name] = $relation_arr[$item[$relation_key]] ?? [];
        });

        return $main_arr;
    }
}

if (!function_exists('formatNum')) {
    /**
     * Notes:保留两位
     * @param $price
     * @return string
     * @User: qc  DateTime: 2020/11/28 17:02
     */
    function formatPrice($price)
    {
        return sprintf("%.2f", $price);
    }
}

if (!function_exists('check_record_auth')) {
    /**
     * 记录 简单验证是否正确
     */
    function checkRecordAuth($string = '')
    {
        return md5(md5($string . 'abcdTESasKFGepgs65s7td5rcxw7'));
    }
}

if (!function_exists('bcCalc')) {
    /**
     * Description:精确计算
     * User: Vijay <1937832819@qq.com>
     * Date: 2020/12/8
     * Time: 18:25
     * @param string $n1 第一个数
     * @param string $symbol 计算符号 + - * / %
     * @param string $n2 第二个数
     * @param string $scale 精度 默认为小数点后两位
     * @return string|null
     */
    function bcCalc($n1, $symbol, $n2, $scale = '6')
    {
        switch ($symbol) {
            case "+"://加法
                $res = bcadd($n1, $n2, $scale);
                break;
            case "-"://减法
                $res = bcsub($n1, $n2, $scale);
                break;
            case "*"://乘法
                $res = bcmul($n1, $n2, $scale);
                break;
            case "/"://除法
                if ($n2 == 0) {
                    $res = 0;
                } else {
                    $res = bcdiv($n1, $n2, $scale);
                }
                break;
            case "%"://求余、取模
                if ($n2 == 0) {
                    $res = 0;
                } else {
                    $res = bcmod($n1, $n2, $scale);
                }
                break;
            default:
                $res = "";
                break;
        }
        return $res;
    }
}
if (!function_exists('isOrdersNumberRepeat')) {
    /**
     * Description:检测订单号是否存在
     * User: Vijay <1937832819@qq.com>
     * Date: 2020/12/7
     * Time: 18:45
     * @param $model
     * @param $shop_uid
     * @param $ordersNumber
     * @return bool
     */
    function isOrdersNumberRepeat($model, $shop_uid = 0, $ordersNumber = '')
    {
        $op = [];
        $op['where'][] = ['order_sn', '=', $ordersNumber];
        $op['field'] = 'id';
        $res = $model->getList($shop_uid, $op);
        if (isset($res['list']) && !empty($res['list'])) {
            return false;
        }
        return true;
    }
}


if (!function_exists('setOrderSn')) {
    /**
     * Description:生成唯一订单号
     * User: Vijay <1937832819@qq.com>
     * Date: 2020/12/8
     * Time: 9:57
     * @param string $prefix 前缀
     * @param int $shop_uid 商家id
     * @param int $user_id 用户id
     * @param bool $repeat 是否重复
     * @return bool|string
     */
    function setOrderSn($prefix = 'MA', $shop_uid = 0, $repeat = false)
    {
        $orderSn = $prefix . date('YmdHis') . uniqueRandNumber();
//        if (isOrdersNumberRepeat($shop_uid, $orderSn) === false) {
//            //重置
//            $orderSn = setOrderSn($shop_uid, true);
//        }
        return $orderSn;
    }
}
if (!function_exists('uniqueRandNumber')) {
    /**
     * Description:
     * User: Vijay <1937832819@qq.com>
     * Date: 2020/12/18
     * Time: 20:39
     * @param int $len
     * @return int
     */
    function uniqueRandNumber($len = 6)
    {
        $min = pow(10, $len - 1);
        $max = pow(10, $len) - 1;
        return mt_rand($min, $max);
    }
}

if (!function_exists('versionToInteger')) {
    /**
     * 版本号转整数 例如　1.0.0=001.000.000=001000000=1000000
     * @param string $ver
     * @return int
     */
    function versionToInteger($ver)
    {
        $ver = explode(".", $ver);
        $v1 = sprintf('%03s', (int)$ver[0] ?? 0);
        $v2 = sprintf('%03s', (int)$ver[1] ?? 0);
        $v3 = sprintf('%03s', (int)$ver[2] ?? 0);
        return (int)"{$v1}{$v2}{$v3}";
    }
}
if (!function_exists('versionToString')) {
    /**
     * 整数版本号转字符串　例如 1000000=001000000=001.000.000=1.0.0
     * @param int $ver
     * @return string
     */
    function versionToString($ver)
    {
        if ($ver > 999) {
            if ($ver > 999999) {
                $ver = $ver . "";
                $v3 = (int)substr($ver, -3);
                $v2 = (int)substr($ver, -6, 3);
                $v1 = (int)substr($ver, 0, strlen($ver) - 6);
            } else {
                $ver = $ver . "";
                $v3 = (int)substr($ver, -3);
                $v2 = (int)substr($ver, 0, strlen($ver) - 3);
                $v1 = 0;
            }
        } else {
            $v3 = $ver;
            $v2 = 0;
            $v1 = 0;
        }
        return "{$v1}.{$v2}.{$v3}";
    }
}

if (!function_exists('getThisMonthTime')) {
    /**
     * Notes: 2020年12月 根据这样的字符串返回开始时间戳和结束时间戳
     * @param $dateStr 2020年12月字符串
     * @param $monthNum : 后几个月为正数,前几个月为负数
     * @return array
     * User: SongX DateTime: 2020-12-23 15:35
     */
    function getThisMonthTime($dateStr, $monthNum = 0)
    {

        $arr = date_parse_from_format('Y-m', $dateStr);
        $time = mktime(0, 0, 0, $arr['month'] + $monthNum, 1, $arr['year']);


        $data['beginTime'] = $time;
        $data['firstDay'] = date("Y-m-01 H:i:s", $data['beginTime']);
        $data['endTime'] = strtotime($data['firstDay'] . " +1 month");
        $data['lastDay'] = date("Y-m-d H:i:s", $data['endTime']);
        return $data;
    }
}

if (!function_exists('getTimeDifference')) {
    /**
     * Description:返回两个时间的时间差时间格式
     * User: Vijay <1937832819@qq.com>
     * Date: 2020/12/26
     * Time: 15:05
     * @param $start
     * @param $end
     * @return string
     */
    function getTimeDifference($start, $end)
    {
        if (!is_numeric($start)) {
            $start = strtotime($start);
        }
        if (!is_numeric($end)) {
            $end = strtotime($end);
        }
        if ($start > $end) {
            $diff_time = $start - $end;
        } else {
            $diff_time = $end - $start;
        }
        $year_t = 3600 * 24 * 365;
        $day_t = 3600 * 24;
        $hours_t = 3600;
        $minute_t = 60;
        $year = floor($diff_time / $year_t);
        $days = floor(($diff_time - $year * $year_t) / $day_t);
        $hours = floor(($diff_time - ($year * $year_t) - ($days * $day_t)) / $hours_t);
        $minute = floor(($diff_time - ($year * $year_t) - ($days * $day_t) - $hours * $hours_t) / $minute_t);
        $seconds = $diff_time - $minute * $minute_t - $hours * $hours_t - $days * $day_t - $year * $year_t;
        $text = '';
        if ($year) {
            $text .= $year . '年';
        }
        if ($days) {
            $text .= $days . '天';
        }
        if ($hours) {
            $text .= $hours . '小时';
        }
        if ($minute) {
            $text .= $minute . '分钟';
        }
//        if ($seconds) {
//            $text .= $seconds . '秒';
//        }
        return $text;
    }
}

if (!function_exists('logs')) {
    /**
     * Notes:写日志
     * @param null $data
     * @param null $fileName
     * @return mixed
     * @User: qc  DateTime: 2020/12/26 18:17
     */
    function logs($data = null, $fileName = null)
    {
        if (is_null($data) || is_null($fileName)) {
            $out_arr['code'] = '400004';
            return $out_arr;
        }

        $path = env('app_path') . '../runtime/log/' . $fileName;

        if (!is_dir($path)) {
            $mkdir_re = mkdir($path, 0777, TRUE);
            if (!$mkdir_re) {
//                $this->logs($data, $fileName);
            }
        }

        $filePath = $path . "/" . date("Y-m-d", time());

        $time = date("Y-m-d H:i:s", time());
        $re = file_put_contents($filePath, $time . " " . var_export($data, TRUE) . "\r\n\r\n", FILE_APPEND);

        if (!$re) {
            logs($data, $fileName);
        } else {
            $out_arr['code'] = '000000';
            return $out_arr;
        }
    }
}
if (!function_exists('RndChar')) {

    function RndChar($length)
    {
        $charArr = array(
            "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
            "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "O", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
            "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"
        );
        $output = '';
        $charCount = count($charArr) - 1;
        for ($a = 0; $a < $length; $a++) {
            @mt_srand();
            $output .= $charArr[mt_rand(0, $charCount)];
        }
        return $output;
    }
}
if (!function_exists('FilterRndChar')) {

    function FilterRndChar($length)
    {
        //过滤I,O
        $charArr = array(
            "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
            "A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "M", "N", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
            "a", "b", "c", "d", "e", "f", "g", "h", "j", "k", "m", "n", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"
        );
        $output = '';
        $charCount = count($charArr) - 1;
        for ($a = 0; $a < $length; $a++) {
            @mt_srand();
            $output .= $charArr[mt_rand(0, $charCount)];
        }
        return $output;
    }
}


if (!function_exists('setCrossHeader')) {
    function setCrossHeader($origin)
    {
        header("Access-Control-Allow-Origin: {$origin}"); // 不允许用 *
        header("Access-Control-Allow-Credentials:true");
        header("Access-Control-Allow-Methods:GET,PUT,POST,DELETE,OPTIONS");
        header("Access-Control-Allow-Headers:Set-Cookie, X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Content-Disposition, Date, X-Api-Version, app-from, app-type, app-version, shop-uid, authorization, applet-appid, store-id");
        header("Access-Control-Expose-Headers:Content-Disposition");
    }
}

if (!function_exists('lock_url')) {
    /**
     * 加密函数
     * */
    function lock_url($txt, $key = 'shop_user_login_key_')
    {
        $chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-=+";
        $nh = rand(0, 64);
        $ch = $chars[$nh];
        $mdKey = md5($key . $ch);
        $mdKey = substr($mdKey, $nh % 8, $nh % 8 + 7);
        $txt = base64_encode($txt);
        $tmp = '';
        $i = 0;
        $j = 0;
        $k = 0;
        for ($i = 0; $i < strlen($txt); $i++) {
            $k = $k == strlen($mdKey) ? 0 : $k;
            $j = ($nh + strpos($chars, $txt[$i]) + ord($mdKey[$k++])) % 64;
            $tmp .= $chars[$j];
        }
        return urlencode($ch . $tmp);
    }
}

if (!function_exists('unlock_url')) {
    /**
     * 解密函数
     * */
    function unlock_url($txt, $key = 'shop_user_login_key_')
    {
        $txt = urldecode($txt);
        $chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-=+";
        $ch = $txt[0];
        $nh = strpos($chars, $ch);
        $mdKey = md5($key . $ch);
        $mdKey = substr($mdKey, $nh % 8, $nh % 8 + 7);
        $txt = substr($txt, 1);
        $tmp = '';
        $i = 0;
        $j = 0;
        $k = 0;
        for ($i = 0; $i < strlen($txt); $i++) {
            $k = $k == strlen($mdKey) ? 0 : $k;
            $j = strpos($chars, $txt[$i]) - $nh - ord($mdKey[$k++]);
            while ($j < 0) $j += 64;
            $tmp .= $chars[$j];
        }
        return base64_decode($tmp);
    }
}

if (!function_exists('getSmsKey')) {
    function getSmsKey($mobile, $type = 0)
    {
        switch ($type) {
            case 1:
                $key = 'official_website_shop_user_mobile_register_' . $mobile;
                break;
            case 2:
                $key = 'official_website_shop_user_mobile_login_' . $mobile;
                break;
            case 3:
                $key = 'user_activity_shipping_address_check' . $mobile;
                break;
            default:
                $key = 'official_website_shop_user_mobile_other_' . $mobile;
        }
        return $key;
    }
}

if (!function_exists('SendSmsCode')) {
    function SendSmsCode($mobile, $type = 0, $shop_uid = 0)
    {
        $key = getSmsKey($mobile, $type);
        if (empty($mobile)) return errorReturn(['code' => 2000, 'msg' => '请输入手机号!']);
        $code = mt_rand(1000, 9999);
        $sms_param = [
            'RegionId' => "cn-hangzhou",
            'PhoneNumbers' => $mobile,
            'SignName' => env('sms.alisms_sign_name'),
            'TemplateCode' => 'SMS_163195078',
            'TemplateParam' => json_encode(['code' => $code]),
            'shop_uid' => $shop_uid,
        ];
        $sms_service = new AliyunSmsService();
        $return_msg = $sms_service->sendSms($sms_param);
        //添加短信发送日志记录
        $logArr = [
            'uid' => 0,
            'type' => 1,
            'send_phone' => $mobile,
            'param' => $code,
            'order_sn' => '',
            'send_sms_code' => $sms_param['TemplateCode'],
            'return_code' => $return_msg['Code'],
            'return_msg' => $return_msg['Message'],
            'send_time' => time(),
        ];
        \app\common\service\shop\ShopSmsRecordService::addLog(0, $logArr);

        if ($return_msg['Code'] == 'OK') {
            \think\facade\Cache::set($key, $code, 500);
            return successReturn(['msg' => '短信发送成功']);
        } else {
            return errorReturn('短信发送失败!');
        }
    }
}
/**
 * 数据脱敏
 * @param $string 需要脱敏值
 * @param int $start 开始
 * @param int $length 结束
 * @param string $re 脱敏替代符号
 * @return bool|string
 * 例子:
 * dataDesensitization('18811113683', 3, 4); //188****3683
 * dataDesensitization('乐杨俊', 0, -1); //**俊
 */
if (!function_exists('dataDesensitization')) {
    function dataDesensitization($string, $start = 0, $length = 0, $re = '*')
    {
        if (empty($string)) {
            return false;
        }
        $strarr = array();
        $mb_strlen = mb_strlen($string);
        while ($mb_strlen) {//循环把字符串变为数组
            $strarr[] = mb_substr($string, 0, 1, 'utf8');
            $string = mb_substr($string, 1, $mb_strlen, 'utf8');
            $mb_strlen = mb_strlen($string);
        }
        $strlen = count($strarr);
        $begin = $start >= 0 ? $start : ($strlen - abs($start));
        $end = $last = $strlen - 1;
        if ($length > 0) {
            $end = $begin + $length - 1;
        } elseif ($length < 0) {
            $end -= abs($length);
        }
        for ($i = $begin; $i <= $end; $i++) {
            $strarr[$i] = $re;
        }
        if ($begin >= $end || $begin >= $last || $end > $last) return false;
        return implode('', $strarr);
    }
}

if (!function_exists('downloadImage')) {
    /**
     * 远程下载图片到指定目录
     * @param $remoteFileUrl
     * @param string $saveFilePath
     * @return \Psr\Http\Message\ResponseInterface
     * User: cwh  DateTime:2021/1/23 16:49
     */
    function downloadImage($remoteFileUrl, $saveFilePath = '', $dirname = '', $is_oss = false)
    {
        try {
            if ($is_oss) {
                $ext = strrchr($remoteFileUrl, '.');
                $ext = cut('.', '?', $ext);
                $filename = date('Ymd') . '.' . $ext;
            } else {
                $filename = pathinfo($remoteFileUrl, PATHINFO_BASENAME);
            }
            if (empty($saveFilePath)) {
                $dirname = pathinfo(parse_url($remoteFileUrl, PHP_URL_PATH), PATHINFO_DIRNAME);
                $fullpath = 'upload' . $dirname . '/' . $filename;
                $path = 'upload' . $dirname . '/';
            } else {
                $fullpath = 'upload' . $saveFilePath . '/' . $filename;
                $path = 'upload' . $saveFilePath . '/';
            }
            if (!is_dir($path)) {
                mkdir($path, 0777, true);
            }
            $client = new \GuzzleHttp\Client([
                'timeout' => 3000,
                'verify' => false
            ]);
            $response = $client->get($remoteFileUrl, ['save_to' => $fullpath]);
            if (file_exists($fullpath)) {
                return $fullpath;
            }
            return $response;
        } catch (\Exception $e) {
            return false;
        }
    }
}
if (!function_exists('cut')) {
    /**
     * Notes: 截取两个特定字符串之间的字符
     * @param $mark1
     * @param $mark2
     * @param $kw1
     * @return false|int|string
     * @author chenyanmu
     * @date 2021-03-24 10:07
     */
    function cut($mark1, $mark2, $kw1)
    {
        $kw = $kw1;
        $kw = '123' . $kw . '123';
        $st = stripos($kw, $mark1);
        $ed = stripos($kw, $mark2);
        if (($st == false || $ed == false) || $st >= $ed)
            return 0;
        $kw = substr($kw, ($st + 1), ($ed - $st - 1));
        return $kw;
    }
}

if (!function_exists('getTotalMillisecond')) {
    /*
     *返回字符串的毫秒数时间戳
     */
    function getTotalMillisecond()
    {
        $time = explode(" ", microtime());
        $time = $time [1] . ($time [0] * 1000);
        $time2 = explode(".", $time);
        $time = $time2 [0];
        return intval($time);
    }

}

if (!function_exists('excelImport')) {
    /**
     * Notes:excel导入
     * @param $file
     * @return mixed
     * @User: qc  DateTime: 2021/1/23 16:42
     */
    function excelImport($file)
    {
        $tmp = $file->getInfo();
        $config = ['path' => ''];
        $excel = new \Vtiful\Kernel\Excel($config);
        $results_array = $excel->openFile($tmp['tmp_name'])
            ->openSheet()
            ->getSheetData();
        return $results_array;
    }
}

if (!function_exists('exportWithXlsWriter')) {
    /**
     * Notes:导出excel
     * @param string $filename
     * @param array $header
     * @param array $data
     * User: qc DateTime: 2022/2/17 10:11
     */
    function exportWithXlsWriter(string $filename, array $header, array $data)
    {
        $config = ['path' => './'];
        $excel = new \Vtiful\Kernel\Excel($config);

        $filePath = $excel->fileName($filename . '.xlsx', 'sheet1')
            ->header($header)
            ->data($data)
            ->output();

        header("Content-Type: application/octet-stream;charset=UTF-8");
        if (strstr(Request::header('User-Agent'), 'Firefox')) {
            header('Content-Disposition: attachment;filename="' . $filename . '.xlsx"');
        } else {
            header('Content-Disposition: attachment;filename="' . urlencode($filename) . '.xlsx"');
        }
        header('Cache-Control: max-age=0');

        if (copy($filePath, 'php://output') === false) {
            // Throw exception
        }
        @unlink($filePath);
        exit();
    }
}


if (!function_exists('homeModuleCheckbox')) {
    function homeModuleCheckbox()
    {
        $checkbox = [
            ['title' => '视频列表', 'url' => '/HomeModule/emptyModule', 'value' => 'explosive'],
            ['title' => '视频详情', 'url' => '/Video/chooseVideo', 'value' => 'explosiveVideo'],
            ['title' => '案例列表', 'url' => '/HomeModule/emptyModule', 'value' => 'case'],
            ['title' => '案例详情', 'url' => '/PatternCase/chooseCase', 'value' => 'caseDetails'],
            ['title' => '设计师列表', 'url' => '/HomeModule/emptyModule', 'value' => 'designer'],
            ['title' => '设计师详情', 'url' => '/JobUser/chooseUser', 'value' => 'designerDetails'],
            ['title' => '工长列表', 'url' => '/HomeModule/emptyModule', 'value' => 'worker'],
            ['title' => '工长详情', 'url' => '/ShopForeman/chooseForeman', 'value' => 'workerDetails'],
            ['title' => '资讯列表', 'url' => '/HomeModule/emptyModule', 'value' => 'decoration'],
            ['title' => '资讯详情', 'url' => '/article/choosegl', 'value' => 'decorationDetails'],
            ['title' => '商品详情', 'url' => '/HomeModule/selectOneGoods', 'value' => 'goodsDetails'],
            ['title' => '商品分类', 'url' => '/goods/selectCategory', 'value' => 'searchList'],
            ['title' => '商品热词', 'url' => '/HomeModule/emptyModule', 'value' => 'search'],
            ['title' => '专题详情', 'url' => '/ShopSubject/chooseSubject', 'value' => 'categoryList'],
            ['title' => '拼团列表', 'url' => '/HomeModule/emptyModule', 'value' => 'group'],
            ['title' => '预约活动详情', 'url' => '/ActivityDecorate/chooseActivity', 'value' => 'activityDetails'],
            ['title' => '自定义页面', 'url' => '/CustomPage/choosePage', 'value' => 'custom'],
            ['title' => '秒杀列表', 'url' => '/HomeModule/emptyModule', 'value' => 'seckill'],
            ['title' => '新人专享', 'url' => '/HomeModule/emptyModule', 'value' => 'newGift'],
            ['title' => '会员开通', 'url' => '/HomeModule/emptyModule', 'value' => 'memberVip'],
            ['title' => '领券中心', 'url' => '/HomeModule/emptyModule', 'value' => 'couponsList'],
            ['title' => '关于我们', 'url' => '/HomeModule/emptyModule', 'value' => 'company'],
            ['title' => '企业动态', 'url' => '/HomeModule/emptyModule', 'value' => 'company?type=1'],
            ['title' => '3d体验馆列表', 'url' => '/HomeModule/emptyModule', 'value' => 'caseHall'],
            ['title' => '家装贷', 'url' => '/HomeModule/webUrl?default_url=' . 'https://' . env('JZD.JZD_DOMAIN') . '.' . env('ROUTE.DOMAIN_TOP'), 'value' => 'webUrl'],
            ['title' => '网页链接', 'url' => '/HomeModule/webUrl', 'value' => 'webUrl'],
            ['title' => '物流服务', 'url' => '/HomeModule/emptyModule', 'value' => 'logisticsServicesInquiry', 'app_page' => 'guest/logistics-services/inquiry/list', 'type' => 2, 'plugin_id' => 4],
            ['title' => '商品采购', 'url' => '/HomeModule/webUrl?default_url=' . sprintf("https://%s.%s/pages/goodsPurchase/index", env('JZD.JZD_DOMAIN'), env('ROUTE.DOMAIN_TOP')), 'value' => 'webUrl', 'app_page' => '', 'type' => 2],
            ['title' => '招商加盟', 'url' => '/HomeModule/webUrl?default_url=/activity/investment/index', 'value' => 'webUrl', 'app_page' => '', 'type' => 2],
            ['title' => '商家入驻', 'url' => '/HomeModule/emptyModule', 'value' => 'shopCreate', 'app_page' => '', 'type' => 2],
            ['title' => '商场信息', 'url' => '/HomeModule/webUrl?default_url=/guest/shopping/index', 'value' => 'webUrl', 'app_page' => '', 'type' => 2],
            ['title' => '楼层导视', 'url' => '/HomeModule/webUrl?default_url=https://' . env('JZD.JZD_DOMAIN') . '.' . env('ROUTE.DOMAIN_TOP') . '/pages/floorNav/index', 'value' => 'webUrl', 'app_page' => '', 'type' => 2],
            ['title' => '邀请函', 'url' => '/HomeModule/emptyModule', 'value' => 'theInvitation'],
            ['title' => '积分商城', 'url' => '/HomeModule/emptyModule', 'value' => 'integralGoods'],
            ['title' => '名片详情', 'url' => '/HomeModule/emptyModule', 'value' => 'businessCard'],
            ['title' => '门店列表', 'url' => '/HomeModule/emptyModule', 'value' => 'shopList'],
            ['title' => '门店详情', 'url' => '/ShopStore/chooseStore', 'value' => 'shopDetail'],
        ];
        $shopUid = session('shop_uid') ?? 0;
        if (intval($shopUid) <= 0) {
            return $checkbox;
        }
        $pluginIds = \app\common\service\plugin\ShopUserPluginService::getUsedList($shopUid);
        $pluginIds = array_column($pluginIds, 'plugin_id');
        $result = [];
        foreach ($checkbox as $item) {
            if (!isset($item['plugin_id'])) {
                $result[] = $item;
                continue;
            }

            if (in_array($item['plugin_id'], $pluginIds)) {
                $result[] = $item;
                continue;
            }
        }

        $version = \app\common\service\ShopProductVersionService::getVersionInfo($shopUid, 'broad');
        if (isset($version['data']['status']) && $version['data']['status'] == 1) {
            $result[] = ['title' => '直播列表', 'url' => '/HomeModule/emptyModule', 'value' => 'live'];
        }
        $version = \app\common\service\ShopProductVersionService::getVersionInfo($shopUid, 'credit');
        if (isset($version['data']['status']) && $version['data']['status'] == 1) {
            $result[] = ['title' => '我的积分', 'url' => '/HomeModule/emptyModule', 'value' => 'myIntegral'];
        }

        return $result;
    }
}

if (!function_exists('storeHomeModuleCheckbox')) {
    function storeHomeModuleCheckbox()
    {
        $checkbox = [
            ['title' => '商品详情', 'url' => '/HomeModule/selectOneGoods', 'value' => 'goodsDetails'],
            ['title' => '商品分类', 'url' => '/goods/selectCategory', 'value' => 'searchList'],
        ];
        $result = [];
        foreach ($checkbox as $item) {
            if (!isset($item['plugin_id'])) {
                $result[] = $item;
                continue;
            }
        }

        return $result;
    }
}

if (!function_exists('setTime')) {
    function setTime($targetTime)
    {
        //今天最小时间
        $todayLasted = strtotime(date('Y-m-d 00:00:00'));
        $abortTime = is_int($targetTime) ? $targetTime : strtotime($targetTime);
        $afterTimeTrue = $abortTime - time();
        $afterTime = $abortTime - $todayLasted;
        $afterDay = floor($afterTime / 86400);
        $result = $targetTime;

        if ($afterTimeTrue < 0) {
            return '未开播';
        }

        $hour = date('H:i', $abortTime);
        if ($afterTimeTrue > 0 && $afterTimeTrue < 3600) {
            $result = (ceil($afterTimeTrue / 60)) . '分钟后';
        } elseif ($afterTimeTrue < 3600 * 12) {
            $result = (ceil($afterTimeTrue / 3600)) . '小时后';
        } elseif ($afterDay == 0) {
            $result = '今天 ' . $hour;
        } elseif ($afterDay == 1) {
            $result = '明天 ' . $hour;
        } elseif ($afterDay == 2) {
            $result = '后天 ' . $hour;
        } elseif ($afterDay > 2 && $afterDay < 8) {
//            $result = $afterDay . '天后';
            $result = date('Y-m-d', $abortTime);
        }
        return $result;
    }
}

if (!function_exists('searchMultiArray')) {
    //二维数组搜索指定value的值
    function searchMultiArray($array, $search_key, $search_value)
    {
        $rs = array_filter($array,
            function ($t) use ($search_key, $search_value) {
                if (is_array($search_value)) {
                    return in_array($t[$search_key], $search_value);
                }
                return $t[$search_key] == $search_value;
            });
        return $rs;
    }
}

if (!function_exists('filterEmpty')) {
    //过滤数组空值，但是不处理0和false的情况
    function filterEmpty($list)
    {
        return array_filter($list, function ($arr) {
            if ($arr === '' || $arr === null) {
                return false;
            }
            return true;
        });
    }
}

if (!function_exists('getShopUserLoginToken')) {
    function getShopUserLoginToken($shop_uid)
    {
        $key = "get_shop_user_login_token";
        return md5($key . $shop_uid);
    }
}
if (!function_exists('getStoreUserLoginToken')) {
    function getStoreUserLoginToken($shop_uid, $store_id)
    {
        $key = "get_store_user_login_token";
        return md5($key . $shop_uid . $store_id);
    }
}

if (!function_exists('get_http_type')) {
    function get_http_type()
    {
        $http_type = ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')) ? 'https://' : 'http://';
        return $http_type;
    }
}

if (!function_exists('match_chinese')) {
    function match_chinese($chars, $encoding = 'utf8')
    {
        $pattern = ($encoding == 'utf8') ? '/[\x{4e00}-\x{9fa5}a-zA-Z0-9]/u' : '/[\x80-\xFF]/';
        preg_match_all($pattern, $chars, $result);
        return join('', $result[0]);
    }
}

if (!function_exists('queryAllDb')) {
    function queryAllDb($model, $pk, $op)
    {
        $sum = 0;
        $model = ('app\\common\\model\\' . $model);
        for ($i = 0; $i <= 9; $i++) {
            $query = (new $model(['shop_uid' => $i]))->where($op['where'] ?? []);
            if (isset($op['alias'])) {
                $query->alias($op['alias']);
            }
            if (isset($op['join'])) {
                $query->join($op['join']);
            }
            if (isset($op['group'])) {
                $query->group($op['group']);
            }
            if (isset($op['having'])) {
                $query->having($op['having']);
            }
            if (isset($op['order'])) {
                $query->order($op['order']);
            }
            if (isset($op['limit'])) {
                $query->limit($op['limit']);
            }
            if (isset($op['sum'])) {
                $sum += $query->sum($op['sum']);
            } else {
                $sum += $query->count($pk);
            }
        }
        return $sum;
    }
}

if (!function_exists('get_app_type')) {
    function get_app_type()
    {
        return \request()->header('app-type');
    }
}
if (!function_exists('get_parent_shop_uid')) {
    function get_parent_shop_uid()
    {
        return \request()->header('parent-shop-uid') ?? 0;
    }
}
if (!function_exists('get_mini_user_version')) {
    function get_mini_user_version()
    {
        return \request()->header('user_version');
    }
}

if (!function_exists('app_review')) {
    //小程序审核判断
    function app_review($shop_uid)
    {
        $wechat_release = getShopTemplateInfo($shop_uid);
        if (empty($wechat_release)) {
            return false;
        }
        $examine_status = [WeChatReleaseService::EXAMINE_STATUS_USED, WeChatReleaseService::PURCHASE_STATUS_DELAY];
        if (!empty($wechat_release) && in_array($wechat_release['examine_status'], $examine_status)) {
            //审核中屏蔽强登录
            return true;
        }
        return false;
    }
}

if (!function_exists('getShopTemplateInfo')) {
    //获取商家使用的小程序模版
    function getShopTemplateInfo($shop_uid)
    {
        if (get_app_type() == 0 || get_app_type() == 7 || get_app_type() == 9) {
            $user_version = get_mini_user_version();
            $wechat_release = WeChatReleaseService::getCurrentWxTemplate($shop_uid, $user_version);
            return $wechat_release;
        }
        return false;
    }
}

if (!function_exists('getAdminGoodsRightRole')) {
    //admin后台商品管理权限的角色ID
    function getAdminGoodsRightRole()
    {
        return [1, 2, 5, 7, 10, 12, 14, 18, 23, 25, 26];
    }
}

if (!function_exists('convertUrlQuery')) {
    function convertUrlQuery($url, $key, $value)
    {
        $url = parse_url(htmlspecialchars_decode($url));
        $query = $url['query'] ?? [];
        //参数空的时候直接返回
        if (empty($url['query'])) return $url['path'] . '?' . $key . '=' . $value;

        $queryParts = explode('&', $query);
        $params = array();
        foreach ($queryParts as $param) {
            $item = explode('=', $param);
            if ($item[0] == $key) {
                $params[$item[0]] = $value;
            } else {
                $params[$item[0]] = $item[1];
            }
        }
        if (!isset($params[$key])) $params[$key] = $value;

        $tmp = array();
        foreach ($params as $k => $v) {
            $tmp[] = $k . '=' . $v;
        }
        $params = implode('&', $tmp);
        return $url['path'] . '?' . $params;
    }
}

if (!function_exists("hiddenStr")) {
    /**
     * Description:隐藏字符串
     * User: linwenye <343968696@qq.com>
     * @param string $str 需要隐藏的字符串
     * @param int $n 前面显示多少个字符
     * @param int $e 后面显示多少个字符
     * @param int $m 中间放多少个*
     * @return mixed
     * Date:2021/07/01
     * Time:16:10
     */
    function hiddenStr(string $str, int $n, int $e, int $m = 2): string
    {
        $str = (string)$str;
        $len = mb_strlen($str);
        if ($len < ($n + $e)) {
            return $str . '*';
        }
        $start = mb_substr($str, 0, $n);
        $end = mb_substr($str, $len - $e, $e);
        $middle = "";
        for ($i = 0; $i < $m; $i++) {
            $middle .= "*";
        }
        return $start . $middle . $end;
    }
}

if (!function_exists('createSign')) {
    /**
     * 生成待签名参数串
     * @access public
     * @param array $param 业务参数
     * @param string $shopKey 商户md5密钥
     * return string
     * @return string
     */
    function createSign(array $param = [], string $shopKey = '')
    {
        ksort($param);
        $string = '';
        foreach ($param as $key => $val) {
            if (is_array($val)) {
                array_walk($val, function (&$value, $key) {
                    $value = (string)$value;
                });
                $val = json_encode($val);
            }
            if (is_numeric($val)) $val = (string)$val;
            if ($key != '' && $val != '') {
                $string .= $key . '=' . (string)$val . '&';
            }
        }
        $string .= 'key=' . $shopKey;
        return $string;
    }
}


//根据时间戳范围 返回时间范围内的 日期[]
if (!function_exists('getDateFromRange')) {
    function getDateFromRange($stimestamp, $etimestamp)
    {
        // 计算日期段内有多少天
        $days = ($etimestamp - $stimestamp) / 86400 + 1;
        // 保存每天日期
        $date = array();
        for ($i = 0; $i < $days; $i++) {
            $date[] = date('Y-m-d', $stimestamp + (86400 * $i));
        }
        return $date;
    }
}

if (!function_exists('rand_investor_data')) {
    function rand_investor_data($config, $field)
    {
        if (!isset($config[$field])) {
            return 0;
        }
        $range = explode('-', $config[$field]);
        if (count($range) == 2 &&
            $range[0] >= 0 &&
            $range[1] > 0 &&
            $range[1] > $range[0]
        ) {
            return rand($range[0], $range[1]);
        }

        return 0;
    }
}

if (!function_exists('create_range')) {
    /**
     * 按步长分组时间
     * @param $start
     * @param $end
     * @param int $step
     * User: xdf
     * Date: 2021/5/29
     * Time: 10:30
     * @return array
     */
    function create_date_range($start, $end, $step = 2)
    {
        $newDate = [];
        for ($i = $start; $i <= $end; $i += 86400) {
            $newDate[] = $i;
        }

        $result = [];
        $newDate = array_chunk($newDate, $step);
        foreach ($newDate as $dateVal) {
            $first = array_shift($dateVal);
            $last = array_pop($dateVal);
            $last = empty($last) ? $first : $last;
            $result[] = [
                $first, $last
            ];
        }
        return $result;
    }
}

if (!function_exists('create_every_day')) {
    function create_every_day($start, $end)
    {
        $newDate = [];
        for ($i = $start; $i <= $end; $i += 86400) {
            $newDate[] = $i;
        }
        return $newDate;
    }
}
if (!function_exists('substr_replace_cn')) {
    /**
     * Description:替换字符串
     * User: Vijay <1937832819@qq.com>
     * Date: 2021/7/22
     * Time: 15:11
     * @param string $string 要替换的字符串
     * @param string $repalce 需要替换成
     * @param int $start 开始位置
     * @param int $len 长度
     * @return string
     */
    function substr_replace_cn(string $string, string $repalce = '*', int $start = 0, int $len = 0): string
    {
        $count = mb_strlen($string, 'UTF-8'); //此处传入编码，建议使用utf-8。此处编码要与下面mb_substr()所使用的一致
        if (!$count) {
            return $string;
        }
        if ($len == 0) {
            $end = $count; //传入0则替换到最后
        } else {
            $end = $start + $len;//传入指定长度则为开始长度+指定长度
        }
        $i = 0;
        $returnString = '';
        while ($i < $count) {//循环该字符串
            $tmpString = mb_substr($string, $i, 1, 'UTF-8'); // 与mb_strlen编码一致
            if ($start <= $i && $i < $end) {
                $returnString .= $repalce;
            } else {
                $returnString .= $tmpString;
            }
            $i++;
        }
        return $returnString;
    }
}


if (!function_exists('splitWhereIn')) {
    /**
     * Notes:拆分whereIn
     * @param array $field_value 拆分的值
     * @param string $field_name 名称
     * @param int $split_num 拆分数量
     * @return array
     * User: qc DateTime: 2021/7/22 14:43
     */
    function splitWhereIn(array $field_value, string $field_name, int $split_num = 2000)
    {
        if (count($field_value) <= $split_num) return [[$field_name, 'in', $field_value]];
        $field_value_split = array_chunk($field_value, $split_num);
        $where[] = function ($query) use ($field_value_split, $field_name) {
            $sql_query = $query;
            foreach ($field_value_split as $key => $value) {
                if ($key == 0) {
                    $sql_query = $sql_query->where($field_name, 'in', $value);
                } else {
                    $sql_query = $sql_query->whereOr($field_name, 'in', $value);
                }
            }
        };
        return $where;
    }
}


if (!function_exists('auth_code')) {
    /**
     * 生成加密解密的字符串
     * @param $string    要加密/解密的字符串
     * @param string $operation 类型，ENCODE 加密；DECODE 解密
     * @param string $key 密匙
     * @param int $expiry 有效期
     * @return string
     */
    function auth_code($string, $operation = 'DECODE', $key = 'saas_decode', $expiry = 0)
    {
        // 动态密匙长度，相同的明文会生成不同密文就是依靠动态密匙
        $ckey_length = 4;
        // 密匙
        $key = md5($key);
        // 密匙a会参与加解密
        $keya = md5(substr($key, 0, 16));
        // 密匙b会用来做数据完整性验证
        $keyb = md5(substr($key, 16, 16));
        // 密匙c用于变化生成的密文
        $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length) :
            substr(md5(microtime()), -$ckey_length)) : '';
        // 参与运算的密匙
        $cryptkey = $keya . md5($keya . $keyc);
        $key_length = strlen($cryptkey);
        // 明文，前10位用来保存时间戳，解密时验证数据有效性，10到26位用来保存$keyb(密匙b)，
        //解密时会通过这个密匙验证数据完整性
        // 如果是解码的话，会从第$ckey_length位开始，因为密文前$ckey_length位保存 动态密匙，以保证解密正确
        $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) :
            sprintf('%010d', $expiry ? $expiry + time() : 0) . substr(md5($string . $keyb), 0, 16) . $string;
        $string_length = strlen($string);
        $result = '';
        $box = range(0, 255);
        $rndkey = array();
        // 产生密匙簿
        for ($i = 0; $i <= 255; $i++) {
            $rndkey[$i] = ord($cryptkey[$i % $key_length]);
        }
        // 用固定的算法，打乱密匙簿，增加随机性，好像很复杂，实际上对并不会增加密文的强度
        for ($j = $i = 0; $i < 256; $i++) {
            $j = ($j + $box[$i] + $rndkey[$i]) % 256;
            $tmp = $box[$i];
            $box[$i] = $box[$j];
            $box[$j] = $tmp;
        }
        // 核心加解密部分
        for ($a = $j = $i = 0; $i < $string_length; $i++) {
            $a = ($a + 1) % 256;
            $j = ($j + $box[$a]) % 256;
            $tmp = $box[$a];
            $box[$a] = $box[$j];
            $box[$j] = $tmp;
            // 从密匙簿得出密匙进行异或，再转成字符
            $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
        }
        if ($operation == 'DECODE') {
            // 验证数据有效性，请看未加密明文的格式
            if ((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) &&
                substr($result, 10, 16) == substr(md5(substr($result, 26) . $keyb), 0, 16)
            ) {
                return substr($result, 26);
            } else {
                return '';
            }
        } else {
            // 把动态密匙保存在密文里，这也是为什么同样的明文，生产不同密文后能解密的原因
            // 因为加密后的密文可能是一些特殊字符，复制过程可能会丢失，所以用base64编码
            return $keyc . str_replace('=', '', base64_encode($result));
        }
    }
}

if (!function_exists('check_auth_code')) {
    /**
     * 验证签名
     * @param $str 解密串
     * @param $header_shop_uid 商家id
     * @param $count  解密串 参数个数
     * @param int $expire_time 过期时间
     * @return \think\response\Json
     * User: cwh  DateTime:2021/6/29 16:51
     */
    function check_auth_code($decrypt_str, $header_shop_uid, $expire_time = 86400, $count = 4)
    {
        $decrypt_str = explode("_", $decrypt_str);
        if (count($decrypt_str) != $count) {
            $returnData['result'] = false;
            $returnData['msg'] = '签名错误1';
            $returnData['code'] = SysEnums::TokenError; //20200
            return $returnData;
        }
        if ($decrypt_str[1] != $header_shop_uid) {
            $returnData['result'] = false;
            $returnData['msg'] = '签名错误2';
            $returnData['code'] = SysEnums::TokenError; //20200
            return $returnData;
        }
        //过期时间，一天
        if ($decrypt_str[3] + $expire_time < time()) {
            $returnData['result'] = false;
            $returnData['msg'] = '签名过期';
            $returnData['code'] = SysEnums::TokenExpiredError; //20200
            return $returnData;
        }
        $returnData['result'] = true;
        $returnData['msg'] = '签名正确';
        $returnData['code'] = 0; //20200
        $returnData['uid'] = $decrypt_str[2];
        return $returnData;
    }
}

if (!function_exists('create_authcode')) {
    /**
     * 生成签名
     * @param $shop_uid
     * @param $uid
     * @return mixed
     * User: cwh  DateTime:2021/6/29 17:37
     */
    function create_authcode($shop_uid, $uid = 0)
    {
        $key = "shop_" . $shop_uid . "_" . $uid . "_" . (time() * 7 * 86400);
        $encrypt = auth_code($key, "ENCODE");
        return $encrypt;
    }
}


if (!function_exists('getZhongDian')) {
    /**
     * Notes:内部公司shop_uid
     * @param bool $isDebug true:测试环境, false:正式
     * @return array
     * User: qc DateTime: 2021/7/22 14:43
     */
    function getZhongDian($isDebug = false)
    {
        if ($isDebug) {   //测试环境
            return [1, 3];
        } else {
            return [3, 676];
        }

    }
}

if (!function_exists('getSchemeDateWeekly')) {
    /**
     * 根据时间段，获取其间各自然周时间戳
     * @param string $beginDateStr
     * @param string $endDateStr
     */

    function getSchemeDateWeekly($beginDateStr = '', $endDateStr = '')
    {
        $beginTimestamp = strtotime(date($beginDateStr));
        $beginWeekRange = actionWeek($beginDateStr);
        $endWeekRange = actionWeek($endDateStr);
        if ($beginWeekRange['end'] < $beginTimestamp) {
            $beginDateStr = date('Y-m-d', $beginWeekRange['end'] + (7 * 24 * 60 * 60));
            $beginWeekRange = actionWeek($beginDateStr);
        }
        $begin_date = date('Y-m-d', $beginWeekRange['start']);
        $end_date = date('Y-m-d', $endWeekRange['end']);
        $weekList = getSchemeDate7days($begin_date, $end_date);
        return $weekList;

    }
}

if (!function_exists('getSchemeDate7days')) {
// 根据时间段按7天来分割时间

    function getSchemeDate7days($begin_date = '', $end_date = '')
    {
        if (!$begin_date || !$end_date) return false;
        $diff_time = strtotime($end_date) + 24 * 60 * 60 - strtotime($begin_date);
        $diff_week = round($diff_time / (7 * 24 * 60 * 60));
        $times_arr = [];
        foreach (range(0, $diff_week - 1) as $item) {
            $times_arr[$item]['begin_date'] = date('Y-m-d', strtotime($begin_date) + (7 * 24 * 60 * 60) * $item);
            $times_arr[$item]['end_date'] = date('Y-m-d', strtotime($times_arr[$item]['begin_date']) + (6 * 24 * 60 * 60));
            $times_arr[$item]['week_num'] = date('W', strtotime($times_arr[$item]['begin_date']));
            if (strtotime($times_arr[$item]['end_date']) > strtotime($end_date)) {
                unset($times_arr[$item]);
            }
        }
        return $times_arr;
    }
}

if (!function_exists('actionWeek')) {
// 根据时间获取最近的自然周起止时间的时间戳
    function actionWeek($timeStr = '')
    {
        $time = strtotime(date($timeStr));
        $startTimestamp = strtotime(date(
            "Y-m-d H:i:s",
            mktime(0, 0, 0, date("m", $time),
                date("d", $time) - date("w", $time) + 1 - 7,
                date("Y", $time)
            )
        ));
        $endTimestamp = strtotime(date(
            "Y-m-d H:i:s",
            mktime(23, 59, 59,
                date("m", $time),
                date("d", $time) - date("w", $time) + 7 - 7,
                date("Y", $time)
            )
        ));
        return ['start' => $startTimestamp, 'end' => $endTimestamp];
    }
}

if (!function_exists('timeTran')) {
    //距离当前时间多久
    function timeTran($time)
    {
        $text = '';
        if (!$time) {
            return $text;
        }
        $current = time();
        $t = $current - $time;
        $retArr = array('刚刚', '秒前', '分钟前', '小时前', '天前', '月前', '年前');
        switch ($t) {
            case $t < 0://时间大于当前时间，返回格式化时间
                $text = date('Y-m-d', $time);
                break;
            case $t == 0://刚刚
                $text = $retArr[0];
                break;
            case $t < 60:// 几秒前
                $text = $t . $retArr[1];
                break;
            case $t < 3600://几分钟前
                $text = floor($t / 60) . $retArr[2];
                break;
            case $t < 86400://几小时前
                $text = floor($t / 3600) . $retArr[3];
                break;
            case $t < 2592000: //几天前
                $text = floor($t / 86400) . $retArr[4];
                break;
            case $t < 31536000: //几个月前
                $text = floor($t / 2592000) . $retArr[5];
                break;
            default : //几年前
                $text = floor($t / 31536000) . $retArr[6];
        }
        return $text;
    }
}


if (!function_exists('getShopToken')) {
    function getShopToken(int $shop_uid, $param = '')
    {
        $key = "get_shop_user_token";
        return md5($key . $shop_uid . $param);
    }
}

if (!function_exists('asyncRequest')) {
    /**
     * Notes:异步请求
     * @param string $url 地址
     * @param array $param 参数
     * @return false|int|string
     * User: qc DateTime: 2021/9/1 11:21
     */
    function asyncRequest(string $url, array $param = [])
    {
        $url_info = parse_url($url);
        $host = $url_info['host'];
        $path = $url_info['path'];
        $query = isset($param) ? http_build_query($param) : '';
        $port = 80;
        $errno = 0;
        $errstr = '';
        $timeout = 30; //连接超时时间（S）

        $fp = @fsockopen($host, $port, $errno, $errstr, $timeout);
        //$fp = stream_socket_client("tcp://".$host.":".$port, $errno, $errstr, $timeout);

        if (!$fp) {
            logs('连接失败', 'async_request_logs');
            throw new \Exception('连接失败');
            return '连接失败';
        }

        if ($errno || !$fp) {
            logs($errstr, 'async_request_logs');
            throw new \Exception($errstr);
            return $errstr;
        }

        stream_set_blocking($fp, 0); //非阻塞
        stream_set_timeout($fp, 3);//响应超时时间（S）
        $out = "POST " . $path . " HTTP/1.1\r\n";
        $out .= "host:" . $host . "\r\n";
        $out .= "content-length:" . strlen($query) . "\r\n";
        $out .= "content-type:application/x-www-form-urlencoded\r\n";
        $out .= "connection:close\r\n\r\n";
        $out .= $query;

        $result = @fputs($fp, $out);
        usleep(1000); // 延迟1毫秒，如果没有这延时，可能在nginx服务器上就无法执行成功
        @fclose($fp);
        return $result;
    }
}

if (!function_exists('dikaer')) {
    /**
     * Notes:返回笛卡尔积
     * @param array $arr
     * @return array|mixed
     * User: qc DateTime: 2021/9/16 18:21
     */
    function dikaer(array $arr)
    {
        $arr1 = array();
        $result = array_shift($arr);
        while ($arr2 = array_shift($arr)) {
            $arr1 = $result;
            $result = array();
            foreach ($arr1 as $v) {
                foreach ($arr2 as $v2) {
                    $result[] = $v . ',' . $v2;
                }
            }
        }
        return $result;
    }
}

if (!function_exists('txMap')) {
    /**
     * Notes:获取腾讯地图
     * @param array $arr
     * @return array|mixed
     * User: qc DateTime: 2021/9/16 18:21
     */
    function txMap(array $data)
    {

        $lat = 39.916527;
        $lng = 116.397128;
        //省份
        $province = RegionService::info($data['province_id'], 'ext_name');
        $province = $province ? $province : '';
        //城市
        $city = RegionService::info($data['city_id'], 'ext_name');
        $city = $city ? $city : '';
        //区
        $district = RegionService::info($data['district_id'], 'ext_name');
        $district = $district ? $district : '';

        $address = $province . $city . $district . $data['address'];
        $geocoder = TxLbs::geocoder(['address' => $address]);
        if ($geocoder) {
            $lng = $geocoder['location']['lng'];
            $lat = $geocoder['location']['lat'];
        }

        return ['lng' => $lng, 'lat' => $lat];
    }
}

if (!function_exists('hideStar')) {
    /**
     * Notes://用户名、邮箱、手机账号中间字符串以*隐藏
     * @param string $str
     * @return string|string[]|null
     * User: qc DateTime: 2021/10/11 14:19
     */
    function hideStar(string $str)
    {
        if (strpos($str, '@')) {
            $email_array = explode("@", $str);
            $prevfix = (strlen($email_array[0]) < 4) ? "" : substr($str, 0, 3); //邮箱前缀
            $count = 0;
            $str = preg_replace('/([\d\w+_-]{0,100})@/', '***@', $str, -1, $count);
            $rs = $prevfix . $str;
        } else {
            $pattern = '/(1[3458]{1}[0-9])[0-9]{4}([0-9]{4})/i';
            if (preg_match($pattern, $str)) {
                $rs = preg_replace($pattern, '$1****$2', $str); // substr_replace($name,'****',3,4);
            } else {
                $rs = substr($str, 0, 3) . "***" . substr($str, -1);
            }
        }
        return $rs;
    }
}

if (!function_exists('removeEmojiChar')) {
    /**
     * Notes:移除字符串中的 emoji 表情
     * @param string $str
     * @return string
     * User: qc DateTime: 2021/10/11 14:43
     */
    function removeEmojiChar(string $str)
    {
        $mbLen = mb_strlen($str);
        $strArr = [];
        for ($i = 0; $i < $mbLen; $i++) {
            $mbSubstr = mb_substr($str, $i, 1, 'utf-8');
            if (strlen($mbSubstr) >= 4) {
                continue;
            }
            $strArr[] = $mbSubstr;
        }
        return implode('', $strArr);
    }
}


if (!function_exists('setTimeGap')) {
    /**
     * Notes:获取时间分组
     * User :Chenyanmu
     * datatime:2021/10/13 16:45
     * @param array $timeRange
     * @return array
     */
    function setTimeGap($start_time, $end_time, $add_time = 86400): array
    {
        $end_time = $end_time + $add_time;
        $count = ($end_time - $start_time) / $add_time;
        $res = [];
        for ($i = 1; $i <= $count; $i++) {
            $res[] = date('Y-m-d', $start_time);
            $start_time += $add_time;
        }
        return $res;
    }
}

if (!function_exists('day_time_array')) {
    /**
     * 根据时间戳的开始时间 和结束时间 生成时间段信息
     * @param $format_date
     * @return array
     */
    function day_time_array($start_time, $end_time, $format = "H", $add_time = 3600)
    {
        $arr = [];
        for ($i = $start_time; $i <= $end_time; $i += $add_time)  //3600秒是按每小时生成一条，如果按天或者月份换算成秒即可
        {
            $date = date($format, $i) . ":00";
            $mdate = date($format, $i);
            $arr[] = $date;
        }
        return $arr;
    }
}

if (!function_exists('reduced_unit')) {
    /**
     * 数字超过万加单位
     * @param $number
     * @param string $unit
     * @return string
     */
    function reduced_unit($number, $unit = '万')
    {
        if ($number >= 10000) {
            # 判断是否超过w
            $newNum = bcdiv($number, 10000, 2) . $unit;
        } else {
            $newNum = $number;
        }
        return $newNum;
    }
}

if (!function_exists('reduced_round_unit')) {
    /**
     * 数字超过万加单位
     * @param $number
     * @param string $unit
     * @return string
     */
    function reduced_round_unit($number, $unit = '万')
    {
        if ($number >= 10000) {
            # 判断是否超过w
            $newNum = round($number/10000, 2).$unit;
        } else {
            $newNum = $number;
        }
        return $newNum;
    }
}

if (!function_exists('postfix_unit')) {
    /**
     * 数字超过万或者少于万 后缀加单位
     * @param $number
     * @param string $unit
     * @return string
     */
    function postfix_unit($number, $unit = '万')
    {
        if ($number >= 10000) {
            # 判断是否超过w
            $newNum = $unit;
        } else {
            $newNum = $unit;
        }
        return $newNum;
    }
}

if (!function_exists('interval_sort')) {

    /**
     * 区间排序
     * @param $data          二维数组
     * @param string $column 指定某一列值
     * @return array
     */
    function interval_sort($data, $column = 'value')
    {
        $avg = array_sum(array_column($data, $column)) / count($data);
        $newData = [];
        $bigOrSmallPrv = null;
        foreach ($data as $key => $item) {
            $bigOrSmallThis = $item[$column] > $avg ? 'big' : 'small';
            //第一次比较平均值
            if ($bigOrSmallPrv === null) {
                $bigOrSmallPrv = $bigOrSmallThis;
                $newData[] = $item;
                unset($data[$key]);
                continue;
            }

            //2次的大小比较不相等的
            if ($bigOrSmallPrv != $bigOrSmallThis && count($data) > 1) {
                $bigOrSmallPrv = $bigOrSmallThis;
                $newData[] = $item;
                unset($data[$key]);
                continue;
            }

            //2次的大小比较相等的, 数组长度只剩下一个的时候
            if (count($data) == 1) {
                $popItem = array_pop($data);
                $newData[] = $popItem;
                unset($data[$key]);
                break;
            }
            //2次的大小比较相等的, 数组长度大于一个的时候
            $thisCount = 1;
            foreach ($data as $k => $v) {
                $bigOrSmallSecForeach = $v[$column] > $avg ? 'big' : 'small';
                if ($bigOrSmallPrv != $bigOrSmallSecForeach) {
                    $bigOrSmallPrv = $bigOrSmallSecForeach;
                    $newData[] = $v;
                    unset($data[$k]);
                    break;
                }

                if ($thisCount == count($data)) {
                    $newData[] = $v;
                    unset($data[$k]);
                    break;
                }
                $thisCount++;
            }
        }
        return $newData;
    }
}

if(!function_exists('getSpecsModelBrand')){
    /**
     * Notes: 尝试提取商品名称中的规格, 型号, 品牌
     * @param string $str
     * @return array
     * User: SongX DateTime: 2021/12/13 18:03
     */
    function getSpecsModelBrand($str){
        //$str = '九阳 （PADOOR） 电烤箱 KX32-J12 550 * 415 * 420mm';
        //$str = '派的（PADOOR）欧式简约实木复合YA-004油漆门卧室门室内门';

        $model = '';    //型号    KX32-J12
        $specs = '';    //规格    550 * 415 * 420mm
        $brand = '';

        //找规格   eg: 550 * 415 * 420mm
        $isMatched = preg_match('/(?<=[^\w])((\d+)(\*|\s|M|m)+){2,3}/', $str, $matches);
        if($isMatched){
            $specs = $matches[0];
        }
        $strNew = str_replace($specs, '', $str);    //替换掉规格     九阳  电烤箱 KX32-J12

        //找品牌   eg: （PADOOR）
        $isMatchesBrand = preg_match('/(（|\().*(）|\))/', $strNew, $matchesBrand);
        if($isMatchesBrand){
            $brand = $matchesBrand[0];
        }
        $strNew = str_replace($brand, '', $strNew);

        //找型号   eg: KX32-J12
        $isMatched2 = preg_match('/(\w+-?\w+)/', $strNew, $matches2);
        if($isMatched2){
            $model = $matches2[0];
        }
        $strNew = str_replace($model, '', $strNew);


        return [
            'model' => $model,
            'specs' => $specs,
            'guige' => $specs,
            'brand' => $brand,
            'name' => $str,
            'rubbish' => $strNew,
        ];
    }
}

if (!function_exists('wash_card')) {
    /**
     * 洗牌算法
     * @param $array array 一维数组
     * @return array
     */
    function wash_card($array){
        $cardNum = count($array);
        for($i= $cardNum - 1; $i>0; $i--){
            //随机数生成器，范围[0, i]
            $rand = mt_rand(0, $i);

            $temp = $array[$i];
            $array[$i] = $array[$rand];
            $array[$rand] = $temp;
        }
        return $array;
    }
}


if (!function_exists('getLetter')) {

    /**
     * Notes:获取最大的数量
     * User :Chenyanmu
     * datatime:2021/12/24 20:19
     * @param $mergeconfig
     * @param $noMergeConfig
     */
    function getLetter($num, $gap = 26)
    {
        //获取整数
        $start = intval($num / $gap);
        $start_float = $num / $gap;
        //如果是整除
        if ($start == $start_float){
            $start--;
        }
        $startLetter = '';
        if ($start) $startLetter = chr($start + 64);

        //获取余数
        $end = $num % $gap;
        $endLetter = 'Z';
        if ($end) $endLetter = chr($end + 64);

        return $startLetter . $endLetter;
    }
}

if(!function_exists('changeTimeType')){

    function changeTimeType($seconds)
    {
        if ($seconds > 3600) {
            $hours = intval($seconds / 3600);
            if ($hours >= 24) $time = '超过一天';
        } else {
            $time = gmstrftime('%H:%M:%S', $seconds);
        }
        return $time;
    }
}




